﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DemoCore.Routings
{
    internal class AsyncResult : IAsyncResult
    {
        public bool IsCompleted { get; set; }

        public WaitHandle AsyncWaitHandle { get; set; }

        public object AsyncState { get; set; }

        public bool CompletedSynchronously { get; set; }

        /// <summary>
        /// 答复
        /// </summary>
        public Message Reply { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public Exception Error { get; set; }

        private HostInfo _Host;
        private RoutingService _Service;
        private IRoutingService _Proxy;
        private MessageBuffer _MessageBuffer;
        private AsyncCallback _Callback;
        private RoutingFilter _Filter;
        private ChannelFactory<IRoutingService> _Channel;

        public AsyncResult(RoutingService service, Message message, AsyncCallback callback, object state)
        {
            this._Service = service;
            this._MessageBuffer = message.CreateBufferedCopy(int.MaxValue);
            this._Callback = callback;
            this.AsyncState = state;
            this._Filter = RoutingManager.Currrent.GetFilter(message.Headers.To.AbsolutePath);
            this._Channel = new ChannelFactory<IRoutingService>(_Filter.Endpoint);//Client配置endpoint Name
            SendToHost();
        }

        private bool SendToHost()
        {
            bool result;
            try
            {
                _Host = RoutingManager.Currrent.GetHost();
                Console.WriteLine(_Host.Address + "：" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff"));
                var endpointAddress = RoutingManager.Currrent.CreateEndpoint(_Host, _Filter.Address);
                _Proxy = _Channel.CreateChannel(endpointAddress);
                AsyncCallback callback = new AsyncCallback(Complete);
                Message message = this._MessageBuffer.CreateMessage();
                _Proxy.BeginProcessRequest(message, callback, AsyncState);
                result = true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                result = false;
            }
            return result;
        }

        private void Complete(IAsyncResult result)
        {
            try
            {
                this.AsyncWaitHandle = result.AsyncWaitHandle;
                this.CompletedSynchronously = result.CompletedSynchronously;
                this.IsCompleted = result.IsCompleted;
                this.Reply = this._Proxy.EndProcessRequest(result);
                if (_Channel != null)
                    this._Channel.Close();
                this._Callback(this);
                HostManager.Default.Success(this._Host);
            }
            catch (Exception ex)
            {
                this._Channel.Abort();
                this.Error = ex;
                this._Callback(this);
            }
        }
    }
}
